home *** CD-ROM | disk | FTP | other *** search
/ CU Amiga Super CD-ROM 19 / CU Amiga Magazine's Super CD-ROM 19 (1998)(EMAP Images)(GB)[!][issue 1998-02].iso / CUCD / Programming / LEDA / source / src / vga / _vga.c next >
Encoding:
C/C++ Source or Header  |  1994-11-16  |  11.6 KB  |  453 lines

  1. /*******************************************************************************
  2. +
  3. +  LEDA  3.1c
  4. +
  5. +
  6. +  _vga.c
  7. +
  8. +
  9. +  Copyright (c) 1994  by  Max-Planck-Institut fuer Informatik
  10. +  Im Stadtwald, 6600 Saarbruecken, FRG     
  11. +  All rights reserved.
  12. *******************************************************************************/
  13.  
  14.  
  15.  
  16. #if defined(__linux__)
  17. #include <stdio.h>
  18. #include <unistd.h>
  19. #include <fcntl.h>
  20. #include <sys/mman.h>
  21. #include <sys/ioctl.h>
  22. #include <sys/termios.h>
  23. #endif
  24.  
  25. #include "vga.h"
  26.  
  27. /* 
  28.  * choosing between VGA 640x480x16 color graphics mode or text mode
  29.  * (part of this code is based on "VGAlib" by Tommy Frandsen)
  30.  */
  31.  
  32. VIDEO_PTR  VIDEO=0;
  33.  
  34. int DISP_WIDTH = 640;
  35. int DISP_MAX_X = 639;
  36. int DISP_HEIGHT= 480;
  37. int DISP_MAX_Y = 479;
  38. int DISP_DEPTH = 4;
  39.  
  40. int LINE_BYTES = 80;
  41.  
  42. #define FONT_SIZE  0x2000
  43.  
  44. /* VGA index register ports */
  45. #define CRT_IC  0x3D4   /* CRT Controller Index - color emulation */
  46. #define CRT_IM  0x3B4   /* CRT Controller Index - mono emulation */
  47. #define ATT_IW  0x3C0   /* Attribute Controller Index & Data Write Register */
  48. #define GRA_I   0x3CE   /* Graphics Controller Index */
  49. #define SEQ_I   0x3C4   /* Sequencer Index */
  50. #define PEL_IW  0x3C8   /* PEL Write Index */
  51. #define PEL_IR  0x3C7   /* PEL Read Index */
  52.  
  53. /* VGA data register ports */
  54. #define CRT_DC  0x3D5   /* CRT Controller Data Register - color emulation */
  55. #define CRT_DM  0x3B5   /* CRT Controller Data Register - mono emulation */
  56. #define ATT_R   0x3C1   /* Attribute Controller Data Read Register */
  57. #define GRA_D   0x3CF   /* Graphics Controller Data Register */
  58. #define SEQ_D   0x3C5   /* Sequencer Data Register */
  59. #define MIS_R   0x3CC   /* Misc Output Read Register */
  60. #define MIS_W   0x3C2   /* Misc Output Write Register */
  61. #define IS1_RC  0x3DA   /* Input Status Register 1 - color emulation */
  62. #define IS1_RM  0x3BA   /* Input Status Register 1 - mono emulation */
  63. #define PEL_D   0x3C9   /* PEL Data Register */
  64.  
  65. /* VGA indexes max counts */
  66. #define CRT_C   24      /* 24 CRT Controller Registers */
  67. #define ATT_C   21      /* 21 Attribute Controller Registers */
  68. #define GRA_C   9       /* 9  Graphics Controller Registers */
  69. #define SEQ_C   5       /* 5  Sequencer Registers */
  70. #define MIS_C   1       /* 1  Misc Output Register */
  71.  
  72. /* VGA registers saving indexes */
  73. #define CRT     0               /* CRT Controller Registers start */
  74. #define ATT     CRT+CRT_C       /* Attribute Controller Registers start */
  75. #define GRA     ATT+ATT_C       /* Graphics Controller Registers start */
  76. #define SEQ     GRA+GRA_C       /* Sequencer Registers */
  77. #define MIS     SEQ+SEQ_C       /* General Registers */
  78. #define END     MIS+MIS_C       /* last */
  79.  
  80.  
  81. /* variables used to shift between monchrome and color emulation */
  82. static int CRT_I;        /* current CRT index register address */
  83. static int CRT_D;        /* current CRT data register address */
  84. static int IS1_R;        /* current input status register address */
  85. static int color_text;        /* true if color text emulation */
  86.  
  87.  
  88. /* BIOS mode 12h - 640x480x16 */
  89. static char g640x480x16_regs[60] = {
  90.   0x5F,0x4F,0x50,0x82,0x54,0x80,0x0B,0x3E,0x00,0x40,0x00,0x00,
  91.   0x00,0x00,0x00,0x00,0xEA,0x8C,0xDF,0x28,0x00,0xE7,0x04,0xE3,
  92.   0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B,
  93.   0x0C,0x0D,0x0E,0x0F,0x01,0x00,0x0F,0x00,0x00,
  94.   0x00,0x0F,0x00,0x20,0x00,0x00,0x05,0x0F,0xFF,
  95.   0x03,0x01,0x0F,0x00,0x06,
  96.   0xE3
  97. };
  98.  
  99.  
  100. /* default RGB values */
  101.  
  102. //                            white black red  green blue  yellow violet orange
  103. //                            cyan  brown pink green grey1 grey2  grey3  grey4
  104. static char RGB_RED[16]  = {  63,   0,    63,   0,   0,    54,    42,    54,   
  105.                                0,  48,    63,   9,   45,   40,    35,     0};
  106.  
  107. static char RGB_GREEN[16]= {  63,   0,     0,  54,    0,   54,    21,    36,  
  108.                               63,  28,    26,  35,   45,   40,    35,     0};
  109.  
  110. static char RGB_BLUE[16] = {  63,   0,     0,   0,   63,   18,    63,     0, 
  111.                               63,  18,    47,   9,   45,   40,    35,     0};
  112.  
  113.  
  114. static char text_regs[60];   /* VGA registers for saved text mode */
  115.  
  116. /* saved text mode palette values */
  117. static char text_red[256];
  118. static char text_green[256];
  119. static char text_blue[256];
  120.  
  121.  
  122. static int initialized = 0;
  123.  
  124. static char font_buf1[FONT_SIZE];  /* saved font data - plane 2 */
  125. static char font_buf2[FONT_SIZE];  /* saved font data - plane 3 */
  126.  
  127.  
  128. static void set_regs(char regs[])
  129. {
  130.     int i;
  131.  
  132.     /* disable video */
  133.     port_in(IS1_R);    
  134.     port_out(0x00, ATT_IW);
  135.  
  136.     /* update misc output register */
  137.     port_out(regs[MIS], MIS_W);
  138.  
  139.     /* synchronous reset on */
  140.     port_out(0x00,SEQ_I);
  141.     port_out(0x01,SEQ_D);    
  142.  
  143.     /* write sequencer registers */
  144.     for (i = 1; i < SEQ_C; i++) {
  145.     port_out(i, SEQ_I);
  146.     port_out(regs[SEQ+i], SEQ_D);
  147.     }
  148.  
  149.     /* synchronous reset off */
  150.     port_out(0x00, SEQ_I);
  151.     port_out(0x03, SEQ_D);    
  152.  
  153.     /* deprotect CRT registers 0-7 */
  154.     port_out(0x11, CRT_I);        
  155.     port_out(port_in(CRT_D)&0x7F, CRT_D);
  156.  
  157.     /* write CRT registers */
  158.     for (i = 0; i < CRT_C; i++) {
  159.     port_out(i, CRT_I);
  160.     port_out(regs[CRT+i], CRT_D);
  161.     }
  162.  
  163.     /* write graphics controller registers */
  164.     for (i = 0; i < GRA_C; i++) {
  165.     port_out(i, GRA_I);
  166.     port_out(regs[GRA+i], GRA_D);
  167.     }
  168.  
  169.     /* write attribute controller registers */
  170.     for (i = 0; i < ATT_C; i++) {
  171.     port_in(IS1_R);   /* reset flip-flop */
  172.     port_out(i, ATT_IW);
  173.     port_out(regs[ATT+i],ATT_IW);
  174.     }
  175. }
  176.  
  177. static void vga_initialize()
  178. {
  179.     int  i, j;
  180.     int mem_fd = -1;  /* /dev/mem file descriptor             */
  181.  
  182.     if (initialized) return;
  183.  
  184.     initialized = 1;
  185.  
  186. #if defined(__linux__)
  187.  
  188. #define GRAPH_SIZE 0x10000
  189. #define GRAPH_BASE 0xa0000
  190.  
  191.     /* get I/O permissions for VGA registers */
  192.     if (ioperm(0x3b4, 0x3df - 0x3b4 + 1, 1)) {
  193.     printf("vgalib: Cannot get I/O permissions.\n");
  194.     exit(-1);
  195.     }
  196.  
  197.     if (( VIDEO = (unsigned char*)valloc(GRAPH_SIZE)) == NULL) {
  198.     printf("vgalib: allocation error \n");
  199.     exit (-1);
  200.      }
  201.  
  202.     if (mem_fd < 0) 
  203.     if ((mem_fd = open("/dev/mem", O_RDWR) ) < 0) {
  204.         printf("vgalib: Cannot open /dev/mem.\n");
  205.         exit (-1);
  206.     }
  207.  
  208.     VIDEO = (unsigned char *)mmap(
  209.     (caddr_t)VIDEO,
  210.     GRAPH_SIZE,
  211.     PROT_READ|PROT_WRITE,
  212.     MAP_SHARED|MAP_FIXED,
  213.     mem_fd,
  214.     GRAPH_BASE);
  215.  
  216. #else
  217. #if defined(__GNUG__)
  218.     VIDEO = (VIDEO_PTR)0xd0000000;
  219. #else
  220. #if defined(__ZTC__) && defined(DOS386)
  221.     VIDEO = (VIDEO_PTR)_x386_mk_protected_ptr(0xa0000);
  222. #else
  223.     VIDEO = (VIDEO_PTR)MK_FP(0xa000,0);
  224. #endif
  225. #endif
  226. #endif
  227.  
  228.  
  229.     /* color or monochrome text emulation? */
  230.     color_text = port_in(MIS_R)&0x01;
  231.  
  232.     /* chose registers for color/monochrome emulation */
  233.     if (color_text) {
  234.     CRT_I = CRT_IC;
  235.     CRT_D = CRT_DC;
  236.     IS1_R = IS1_RC;
  237.     } else {
  238.     CRT_I = CRT_IM;
  239.     CRT_D = CRT_DM;
  240.     IS1_R = IS1_RM;
  241.     }
  242.  
  243.     /* disable video */
  244.     port_in(IS1_R);    
  245.     port_out(0x00, ATT_IW);
  246.  
  247.     /* save text mode palette - first select palette index 0 */
  248.     port_out(0, PEL_IR);
  249.  
  250.     /* read RGB components - index is autoincremented */
  251.     for(i = 0; i < 256; i++) {
  252.     for(j = 0; j < 10; j++) ;   /* delay (minimum 240ns) */
  253.     text_red[i] = port_in(PEL_D);
  254.     for(j = 0; j < 10; j++) ;   /* delay (minimum 240ns) */
  255.     text_green[i] = port_in(PEL_D);
  256.     for(j = 0; j < 10; j++) ;   /* delay (minimum 240ns) */
  257.     text_blue[i] = port_in(PEL_D);
  258.     }
  259.  
  260.     /* save text mode VGA registers */
  261.     for (i = 0; i < CRT_C; i++) {
  262.      port_out(i, CRT_I);
  263.      text_regs[CRT+i] = port_in(CRT_D);
  264.     }
  265.     for (i = 0; i < ATT_C; i++) {
  266.            port_in(IS1_R);
  267.          port_out(i, ATT_IW);
  268.          text_regs[ATT+i] = port_in(ATT_R);
  269.     }
  270.     for (i = 0; i < GRA_C; i++) {
  271.             port_out(i, GRA_I);
  272.             text_regs[GRA+i] = port_in(GRA_D);
  273.     }
  274.     for (i = 0; i < SEQ_C; i++) {
  275.             port_out(i, SEQ_I);
  276.             text_regs[SEQ+i] = port_in(SEQ_D);
  277.     }
  278.     text_regs[MIS] = port_in(MIS_R);
  279.  
  280.     /* shift to color emulation */
  281.     CRT_I = CRT_IC;
  282.     CRT_D = CRT_DC;
  283.     IS1_R = IS1_RC;
  284.     port_out(port_in(MIS_R)|0x01, MIS_W);
  285.  
  286.     /* save font data - first select a 16 color graphics mode */
  287.     set_regs(g640x480x16_regs);
  288.  
  289.     /* save font data in plane 2 */
  290.     port_out(0x04, GRA_I);
  291.     port_out(0x02, GRA_D);
  292.     for(i = 0; i < FONT_SIZE; i++) font_buf1[i] = VIDEO[i];
  293.  
  294.     /* save font data in plane 3 */
  295.     port_out(0x04, GRA_I);
  296.     port_out(0x03, GRA_D);
  297.     for(i = 0; i < FONT_SIZE; i++) font_buf2[i] = VIDEO[i];
  298. }
  299.  
  300.  
  301. void set_palette(int index, int red, int green, int blue)
  302. {
  303.     int i;
  304.  
  305.     /* select palette register */
  306.     port_out(index, PEL_IW);
  307.  
  308.     /* write RGB components */
  309.     for(i = 0; i < 10; i++) ;   /* delay (minimum 240ns) */
  310.     port_out(red, PEL_D);
  311.     for(i = 0; i < 10; i++) ;   /* delay (minimum 240ns) */
  312.     port_out(green, PEL_D);
  313.     for(i = 0; i < 10; i++) ;   /* delay (minimum 240ns) */
  314.     port_out(blue, PEL_D);
  315. }
  316.  
  317.  
  318. void get_palette(int index, int *red, int *green, int *blue)
  319. {
  320.     int i;
  321.  
  322.     /* select palette register */
  323.     port_out(index, PEL_IR);
  324.  
  325.     /* read RGB components */
  326.     for(i = 0; i < 10; i++) ;   /* delay (minimum 240ns) */
  327.     *red = (int) port_in(PEL_D);
  328.     for(i = 0; i < 10; i++) ;   /* delay (minimum 240ns) */
  329.     *green = (int) port_in(PEL_D);
  330.     for(i = 0; i < 10; i++) ;   /* delay (minimum 240ns) */
  331.     *blue = (int) port_in(PEL_D);
  332. }
  333.  
  334. static void vga_clear(int c)
  335. {
  336.   register VIDEO_PTR p;
  337.   register VIDEO_PTR last;
  338.  
  339.   /* set color c */
  340.   port_out(c, GRA_I );
  341.   port_out(0, GRA_D );
  342.  
  343.   /* set mode 0 */
  344.   port_out(0x03, GRA_I );
  345.   port_out(0, GRA_D );
  346.  
  347.   /* write to all bits */
  348.   port_out(0x08, GRA_I );
  349.   port_out(0xFF, GRA_D );
  350.  
  351.   last  = VIDEO + DISP_HEIGHT*LINE_BYTES;
  352.  
  353.   for(p = VIDEO; p < last; p++)  *p = 0;
  354.  
  355. }
  356.  
  357.  
  358. void vga_init(int mode, int root_col)  // mode = 0: Text, 1: 640x480x16 
  359. {
  360.     int i;
  361.  
  362.     vga_initialize();
  363.     
  364.     if (mode == 0)  // TEXT
  365.       { 
  366.         vga_clear(0);
  367.  
  368.         /* restore font data - first select a 16 color graphics mode */
  369.         set_regs(g640x480x16_regs);
  370.  
  371.     /* disable Set/Reset Register */
  372.         port_out(0x01, GRA_I );
  373.         port_out(0x00, GRA_D );
  374.  
  375.         /* restore font data in plane 2 - necessary for all VGA's */
  376.         port_out(0x02, SEQ_I );
  377.         port_out(0x04, SEQ_D );
  378.         for(i = 0; i < FONT_SIZE; i++) VIDEO[i] = font_buf1[i];
  379.  
  380.         /* restore font data in plane 3 - necessary for Trident VGA's */
  381.         port_out(0x02, SEQ_I );
  382.         port_out(0x08, SEQ_D );
  383.         for(i = 0; i < FONT_SIZE; i++) VIDEO[i] = font_buf2[i];
  384.  
  385.         /* change register adresses if monochrome text mode */
  386.         if (!color_text) {
  387.             CRT_I = CRT_IM;
  388.             CRT_D = CRT_DM;
  389.             IS1_R = IS1_RM;
  390.             port_out(port_in(MIS_R)&0xFE, MIS_W);
  391.         }
  392.  
  393.     /* restore text mode VGA registers */
  394.         set_regs(text_regs);
  395.  
  396.         /* restore saved palette */
  397.         for(i = 0; i < 256; i++)
  398.             set_palette(i, text_red[i], text_green[i], text_blue[i]);
  399.  
  400.         DISP_WIDTH = 80;
  401.         DISP_MAX_X = 79;
  402.         DISP_HEIGHT= 25;
  403.         DISP_MAX_Y = 24;
  404.       }
  405.     else // graphics mode
  406.       { 
  407.         /* shift to color emulation */
  408.         CRT_I = CRT_IC;
  409.         CRT_D = CRT_DC;
  410.         IS1_R = IS1_RC;
  411.         port_out(port_in(MIS_R)|0x01, MIS_W);
  412.         set_regs(g640x480x16_regs);
  413.  
  414.         /* set default palette */
  415.         for(i = 0; i < 16; i++)
  416.           set_palette(i, RGB_RED[i], RGB_GREEN[i], RGB_BLUE[i]);
  417.  
  418.         vga_clear(root_col);
  419.  
  420.         LINE_BYTES = 80;
  421.         DISP_WIDTH = 640;
  422.         DISP_MAX_X = 639;
  423.         DISP_HEIGHT= 480;
  424.         DISP_MAX_Y = 479;
  425.         DISP_DEPTH = 4;
  426.       }
  427.  
  428.     /* enable video */
  429.     port_in(IS1_R);
  430.     port_out(0x20, ATT_IW);
  431.  
  432. }
  433.  
  434.  
  435. #if defined(__linux__)
  436.  
  437. char getch() 
  438. { termio save;
  439.   char c = 0;
  440.   ioctl(fileno(stdin), TCGETA, &save);
  441.   termio t = save;
  442.   t.c_cc[VMIN] = 0;
  443.   t.c_cc[VTIME] = 0;
  444.   t.c_lflag = 0;
  445.   ioctl(fileno(stdin), TCSETA, &t);
  446.   read(fileno(stdin), &c, 1);
  447.   ioctl(fileno(stdin), TCSETA, &save);
  448.   return c;
  449. }
  450.  
  451. #endif
  452.